#!/usr/bin/python
# -*- coding: utf-8 -*-

'''
Introduction to Programming in Java - An Interdisciplinary Approach

All code snippets and examples ported to Python by
Scott C. King (revisionx at {gee}ma1l <dot> c0m).


sys is a required import here in order to use command line arguments.
https://docs.python.org/2/tutorial/stdlib.html

random is a required import as a substitute for Java's Math.random()
https://docs.python.org/2/library/random.html


# Exercises - Pages 39 to 45

Syntax:
python exercises_p39.py


Notes:
In order to simplify, all of the examples in this section will have
hard-coded values instead of passing in command line arguments.  All of
the examples will be presented in Python module format.

Grouped exercise sections will not pass Pylint with scores of 10.  This
would require renaming the majority of variables.  In Python you typically
return values from functions, so again, breaking convention here.

'''

import random
import math


def exc_121():
    '''  Exercise 1.2.1:  What does the following sequence of statements do?
         int t = a; b=t; a=b;
    '''

    print 'Exercise 1.2.1'
    output = ''
    a, b, t = 3, 9, 0
    t = a
    b = t
    a = b
    print (output + "A:{}, B:{}, T:{}".format(a, b, t))


def exc_122():
    '''  Write a program that uses Math. si n() and Math. cos ()
         to check that thevalue of cos^2(x) + sin^2(x) is approximately
         1 for any x.  Just print the value.
         Why are the values not always exactly 1?  (In Python they are!) '''

    print '\nExercise 1.2.2'
    print math.pow(math.cos(180), 2) + math.pow(math.sin(180), 2)


def exc_123():
    print '\nExercise 1.2.3'
    a = 5
    b = 10
    print bool((not(a and b) and (a or b)) or ((a and b) or (not(a or b))))


def exc_124():
    print '\nExercise 1.2.4'
    a = 5
    b = 10
    print bool((not(a < b)) and (not(a > b)))


def exc_125():
    ''' The exclusive or operator a for boolean operands is defined to
        be true if they are different, fal se if they are the same. Give a
        truth table for this function.  '''

    print '\nExercise 1.2.5'
    print "\nExclusive Or = 'Not OR'"
    print "B A  Out"
    print "0 0   0"
    print "0 1   1"
    print "1 0   1"
    print "1 1   0\n"


def exc_126():
    ''' Why does 10/3 give 3 and not 3.333333333? '''
    print '\nExercise 1.2.6'
    print 'Q:  Why does 10/3 give 3 and not 3.333333333?'
    print 'A:  In Python, output is integer if inputs are integers.'
    print 'PS:  Python 3 does float division and would return 3.333333333.'

def exc_127():
    '''  Python solutions for this problem given.  Python does not auto-convert
         other types to strings when printing to stdout.  '''
    print '\nExercise 1.2.7'
    print str(2) + 'bc'
    print str(2) + str(3) + 'bc'
    print str(2 + 3) + 'bc'
    print "bc" + str(2 + 3)
    print "bc" + str(2) + str(3)


def exc_128():
    '''  Square root using math.sqrt() function '''
    print '\nExercise 1.2.8'
    x = 144
    print math.sqrt(x)


def exc_129():
    '''  Using ord instead of Java's char  '''
    print '\nExercise 1.2.9'
    print 'b'
    print ('b' + 'c')
    print (ord('a') + ord('4')) # chr is the inverse of ord, also unichr(i)

def exc_1210():
    '''  Python does not overflow ints greater than 2147483647  '''

    print '\nExercise 1.2.10'
    print 'Python converts ints greater than 2147483647 to longs.'
    a = 2147483647
    print a
    print a + 1
    print 2 - a
    print -2 - a
    print 2 * a
    print 4 * a


def exc_1211():
    '''  a = 3.14159, what do each of these print?  '''
    print '\nExercise 1.2.11'
    a = 3.14159
    print a
    print a + 1
    print 8/int(a)
    print 8/a
    print int(8/a)


def exc_1212():
    '''  Leave out math in math.sqrt, what happens in program 1.2.3?  '''
    print '\nExercise 1.2.12'
    print "NameError:  global name 'sqrt' is not defined"
    

def exc_1213():
    ''' What is the value of (Math. sqrt (2) * Math. sqrt (2) == 2) '''
    print (math.sqrt(2) * math.sqrt(2) == 2)


def exc_1214():
    '''  Write a program that takes two positive integers as command-line
         arguments and prints true if either evenly divides the other.  '''
    print '\nExercise 1.2.14'
    a = 10
    b = 5
    print "A = 10, B = 5"
    print (a % b == 0) or (b % a ==0)
    print "A = 3, B = 7"
    a = 3
    b = 7
    print (a % b == 0) or (b % a ==0)
    

def exc_1215():
    '''  Write a program that takes three positive integers as command-line
         arguments and prints true if any one of them is greater than or equal
         to the sum of the other two and false otherwise.  (Note: This
         computation tests whether the three numbers could be the lengths
         of the sides of some triangle.)  '''
    print '\nExercise 1.2.15 - Triangle inequality theorem'

    a, b, c = 5, 10, 3
    print "A: {}, B: {}, C: {}".format(a, b, c)
    print (a + b > c) and (a + c > b) and (b + c > a)
    a, b, c = 12, 8, 10
    print "A: {}, B: {}, C: {}".format(a, b, c)
    print (a + b > c) and (a + c > b) and (b + c > a)
    

def exc_1216():
    ''' A physics student gets unexpected results when using the code
        F = G * massl * mass2 / r * r;
        to compute values according to the formula F = Gmxm21 r2.
        Explain the problem and correct the code. '''

    print '\nExercise 1.2.16 - Order of operations problem'
    print 'F = (G * mass1 * mass2) / (r * r)'    


def exc_1217():
    ''' Give the value of a after the execution of the following sequences '''
    print '\nExercise 1.2.17'
    print 'a = 1; a = a + a; a = a + a; a = a + a'
    a = 1
    a = a + a
    a = a + a
    a = a + a
    print "a: {}".format(a)

    print "a = True; a = !a; a = !a; a = !a"
    a = True
    a = not a
    a = not a
    a = not a
    print "a: {}".format(a)
    print 'a = 2; a = a * a; a = a * a; a = a * a'
    a = 2
    a = a * a
    a = a * a
    a = a * a
    print "a: {}".format(a)


def exc_1218():
    ''' Suppose that x and y are doubl e values that represent the Cartesian
        coordinates of a point (x,y) in the plane. Give an expression whose
        value is the distance of the point from the origin.  '''
    
    print '\nExcercise 1.2.18 - Pythagorean Theorem'
    print "X = 3, Y = 4"
    x = 3
    y = 4
    print math.sqrt((x*x) + (y*y))
    print "X = 9 Y = 12"
    x, y = 9, 12
    print math.sqrt((x*x) + (y*y))


def exc_1219():
    ''' Write a program that takes two i nt values a and b from the command line
        and prints a random integer between a and b. '''

    print '\nExercise 1.2.19'
    a = 10
    b = 20
    print 'Random number between 10 and 20:',
    random_seed = random.random()   # Generates random value in range (0-1]
    random_range = (b - a) + 1
    print int(random_seed * random_range + a)


def exc_1220():
    ''' Write a program that prints the sum of two random integers between 1 and
        6 (such as you might get when rolling dice). '''

    print '\nExercise 1.2.20'
    dice1 = random.random()
    dice2 = random.random()
    print "Dice 1:{}  Dice 2:{}".format(int(dice1 * 6 + 1), int(dice2 * 6 + 1))


def exc_1221():
    ''' Write a program that takes a doubl e value t from the command line and
    prints the value of sin(2t) + sin(3t). '''

    print '\nExercise 1.2.21 - Sin of sin(2t) + sin(3t), t = 5.0'
    t = 5.0
    print math.sin(2 * t) + math.sin(3 * t)


def exc_1222():
    ''' Write a program that takes three double values x0, v0, and t from the
        command line and prints the value of x0 + v0t + gt2/2, where g is the
        constant 9.78033. (Note: This value the displacement in meters after t
        seconds when an object is thrown straight up from initial position x0
        at velocity v0 meters per second.) '''

    print '\nExercise 1.2.22 - x0 + v0t + gt^2/2, x=0, v=30, t=5, g=9.78033'
    x = 0
    v = 30
    t = 5
    g = 9.78033
    print (x + v * t + (g * math.pow(t, 2))/2)


def exc_1223():
    ''' Write a program that takes two int values m and d from the command line
    and prints true if day of month is between 3/20 and 6/20, or false. '''

    print '\nExercise 1.2.23 - Test 1/20, 4/21, 4/15, 5/20 in 3/20-6/20'
    m = 1
    d = 20
    result = ((m >= 3) and (m <= 6)) and ((d > 0) and (d <= 20))
    print "Month = {}, Day = {} In Range: {}".format(m, d, result)
    m = 4
    d = 21
    result = ((m >= 3) and (m <= 6)) and ((d > 0) and (d <= 20))
    print "Month = {}, Day = {} In Range: {}".format(m, d, result)
    m = 4
    d = 15
    result = ((m >= 3) and (m <= 6)) and ((d > 0) and (d <= 20))
    print "Month = {}, Day = {} In Range: {}".format(m, d, result)
    m = 6
    d = 20
    result = ((m >= 3) and (m <= 6)) and ((d > 0) and (d <= 20))
    print "Month = {}, Day = {} In Range: {}".format(m, d, result)


def exc_1224():
    ''' Loan payments. Write a program that calculates the monthly payments
        you would have to make over a given number of years to pay off a loan
        at a given interest rate compounded continuously, taking the number
        of years t,the principal P, and the annual interest rate r as
        command-line arguments. The desired value is given by the formula
        Pe^rt. Use Math.exp(). '''

    print '\nExercise 1.2.24 - P = $2340, r=3.1%, t = 3 years (Ans 2568.06)'
    P = 2340
    r = 3.1/100
    t = 3
    months = 12 * t
    print "Total Owed with Interest: ", (P * math.exp(r * t))
    print "Monthly Payment: ", (P * math.exp(r * t))/months


def exc_1225():
    ''' Wind chill. Given the temperature t (in Fahrenheit) and the wind
        speed v(in miles per hour), the National Weather Service defines
        the effective temperature (the wind chill) to be:
        w = 35.74 + 0.6215 t + (0.4275 t - 35.75) v0-16
        Write a program that takes two double command-line arguments t and v
        and prints out the wind chill.UseMath.pow (a, b) to compute ab.
        Note: The formula is not valid if t is larger than 50 in absolute
        value or if v is larger than 120 or less than 3 (you may assume that
        the values you get are in that range). '''

    print '\nExercise 1.2.25:  Where t=32F, v=20mph (Ans: ~20F)'
    t = 32
    v = 20
    print 35.74 + (.6215 * t) + ((.4275 * t) - 35.75) * math.pow(v, .16)
    

def exc_1226():
    ''' 1.2.26 Polar coordinates. Write a program that converts from Car
        tesian to polar coordinates.Your program should take two real numbers
        x and y on the command line and print the polar coordinates r
        and 0. Use the Javamethod Math.atan2 (y, x) which computes the
        arctangent value of y/x thatis in therange from -ir to it. '''
    
    print '\nExercise 1.2.26:  x = 45, y = 45, Length = 63.63, Ang = .785R'
    x = 45
    y = 45
    print 'Polar Length: ', math.sqrt((x*x) + (y*y))
    print 'Polar Angle:  ', (math.atan2(y, x))


def exc_1227():
    ''' Gaussian random numbers. One way to generate a random
        number taken from the Gaussian distribution is to use the Box-Muller
        formula:
        w = sin(2iTv) (-2lnt/)1/2
        Where u and v are real numbers between 0 and 1 generated by the
        Math. random () method. Write a program StdCaussian that prints out
        a standard Gaussian random variable. '''

    print '\nExercise 1.2.27:  StdGaussian Print Gaussian random variable.'
    v = random.random()
    u = random.random()
    print math.sin(2 * math.pi * v) * math.sqrt((-2 * math.log(u)))


def exc_1228():
    ''' Order check. Write a program that takes three double values x, y, and z
        as command-linearguments and prints true if the values are strictly
        ascending or descending (x<y<z or x>y>z),and false otherwise. '''

    print '\nExercise 1.2.28:  Order Check, T = ascending/descending, F other'
    print 'Trying:  3, 6, 9 - ',
    x, y, z = 3, 6, 9
    print ((x < y) and (y < z)) or ((x > y) and (y > z))
    print 'Trying:  9, 6, 3 - ',
    x, y, z = 9, 6, 3
    print ((x < y) and (y < z)) or ((x > y) and (y > z))
    print 'Trying:  3, 2, 9 - ',
    x, y, z = 3, 2, 9
    print ((x < y) and (y < z)) or ((x > y) and (y > z))
    print 'Trying:  9, 5, 6 - ',
    x, y, z = 9, 5, 6
    print ((x < y) and (y < z)) or ((x > y) and (y > z))


def exc_1229():
    ''' Day of the week. Write a program that takes a date as input and prints
        the day of the week that date falls on. Your program should take three
        command line1.2 Built-in Types of Data parameters: m(month), d (day),
        and y (year). For m, use 1 for January, 2 for February, and so forth.
        For output, print 0 for Sunday, 1 for Monday, 2 for Tuesday, and so
        forth. Use the following formulas, for the Gregorian calendar:
        y0 = y - (14 - m) / 12
        x = y0 + y0/4 - y0/100 + y0/400
        m0 = m + 12 * ((14 - m) / 12) - 2
        d0 = (d + x + (31 * m0) / 12) % 7 '''

    print '\nExercise 1.2.29: Feb 14th, 2000?  - (Monday) = 1'
    print 'Also:  April 4th, 1920 (Sunday) = 0'

    m = 2
    d = 14
    y = 2000

    y0 = y - (14 - m) / 12
    x = y0 + y0/4 - y0/100 + y0/400
    m0 = m + 12 * ((14 - m) / 12) - 2
    d0 = (d + x + (31 * m0) / 12) % 7

    print d0

    m = 4
    d = 4
    y = 1920

    y0 = y - (14 - m) / 12
    x = y0 + y0/4 - y0/100 + y0/400
    m0 = m + 12 * ((14 - m) / 12) - 2
    d0 = (d + x + (31 * m0) / 12) % 7

    print d0


def exc_1230():
    ''' Uniform random numbers. Write a program that prints five uniform random
        values between 0 and 1, their average value, and their minimum and
        maximum value. Use Math. random (), Math. mi n (), and Math. max(). '''

    print '\nExercise 1.2.30 - 5 Uniform Random Numbers'
    a = random.random()
    b = random.random()
    c = random.random()
    d = random.random()
    e = random.random()
    print a, b, c, d, e
    print 'Average :', (a + b + c + d + e) / 5
    print 'Max     :', max(a, b, c, d, e)
    print 'Min     :', min(a, b, c, d, e)


def exc_1231():
    ''' Mercator projection. The Mercatorprojection is a conformal (angle
        preserving) projection that maps latitude 9 and longitude X to
        rectangular coordinates (x, y). It is widely used—for example,
        in nautical charts and in the maps that you print from the web.
        The projection is defined by the equations x = X — X0 and
        y = 1/2 In ((1 + sincp) / (1 —sincp)), where X0 is the longitude
        of the point in the center of the map. Write a program that takes
        \0 and the latitude and longitude of a point from the command line
        and prints its projection. '''

    print '\nExercises 1.2.31 - Mercator Projection'
    latit = 45
    longi = 45
    x = 45 - 0
    y = 5


def main():
    '''  Systematically calls each function in this module.  '''
    exc_121()
    exc_122()
    exc_123()
    exc_124()
    exc_125()
    exc_126()
    exc_127()
    exc_128()
    exc_129()
    exc_1210()
    exc_1211()
    exc_1212()
    exc_1213()
    exc_1214()
    exc_1215()
    exc_1216()
    exc_1217()
    exc_1218()
    exc_1219()
    exc_1220()
    exc_1221()
    exc_1222()
    exc_1223()
    exc_1224()
    exc_1225()
    exc_1226()
    exc_1227()
    exc_1228()
    exc_1229()
    exc_1230()
    
if __name__ == '__main__':
    main()




